package config

import (
	"fmt"
	"errors"
	"reflect"
	"meman/libs/utils/reflectutil"
)


type Config struct  {

	//日志地址
	LogDir string

	//开发模式: prod 工作环境 debug 开发环境
	ReceptionEnv string  `json:"host"`

	//服务地址
	ServerAddr string

	// ListenAddr is the network address for providing extra api calls. rpc 服务
	ListenAddr string

	//auth 配置
	Auth Auth

	//数据库配置
	Database Database
	//redis 配置
	Redis Redis
	//nsq配置,多个ip地址
	Nsq  map[string][]Nsq


}

type Auth struct  {
	AppName string
	AppKey string
	BaseUrl string

	//以下配置一般情况下不需要修改.
	LoginPath string
	GroupPath string
	RolePath string
	InfoPath string
	NemberPath string
	GroupRolePath string
	RoleMailPath string
	GroupMailPath string
	//group同步时间间隔5min
	GroupSyncTime string

}

/**
database 数据库
@attr Host string 地址
@attr Port int 端口
@attr User string 用户
@attr Password string 密码
@attr DbName 数据库名字
 */
type Database struct {
	Read DB
	Write DB
}
type DB struct  {
	Host string       `json:"host"`
	Port int        `json:"port"`
	User string       `json:"user"`
	Password string   `json:"password"`
	DbName string     `json:"dbName"`
}

/**
redis配置
 */
type Redis struct  {
	Addr string
	DbIndex uint8
}

/**
Nsq配置
 */
type Nsq struct {
	Host string
	Port int
	Weight int
}


/**
单例模式,返回当前配置
 */
func(this *Config) GetConfig() *Config  {
	if this == nil {
		if config == nil{
			this = config;
		}else {
			panic("config is nil!")
		}

	}
	return this
}

/**
设置Config , 可以自动将值转换成方法名定义的类型,失败返回错误
@param name string 类方法名
@param value interface{} 方法值
@return error| nil
 */
func(config *Config) SetConfig(name string, value interface{}) error{
	field := reflect.ValueOf(&config).Elem().FieldByName(name)
	if !field.IsValid() {
		return errors.New("field name is not valid!")
	}
	if !field.CanSet() {
		return errors.New("field name can not set!")
	}
	fieldType := field.Type()
	val := reflect.ValueOf(value)
	var err error
	if fieldType != val.Type() {
		val,err = reflectutil.TypeConversion(fmt.Sprintf("%v", value), field.Type().Name())
		if err != nil {
			return err
		}
	}
	field.Set(val)
	return nil
}
